/**
 * Module Name:
 * Description:
 * Calling Sequence
 * 		Input Parameters
 * 		Output Parameters
 * Error Conditions Tested:
 * Error Messages Generated:
 * Original Author:
 * Procedure Creation Date:
 * Modification Log:
 * 	 Who/When/Why
 * Coding Standards Met: "Signed Code Leader(Jaron)"
 * Testing Standards Met: "Signed Test Leader(Jamie)"
 */
import java.io.File;
import java.io.FileNotFoundException;

import javax.swing.filechooser.*;
import javax.swing.*;

/**
 *
 * @author caspert
 */
public class Main2 extends javax.swing.JFrame {

	private static final long serialVersionUID = 1L;
	private String objectFileText;
	private File objectFile1;
	private File objectFile2;
	private File objectFile3;
	private File loadFile;
	private JFileChooser fcOpenOF1;
	private JFileChooser fcOpenOF2;
	private JFileChooser fcOpenOF3;
	private JFileChooser fcSave;
	private FileNameExtensionFilter txtFilter;

	private javax.swing.JSeparator bottomSeparator;
	private javax.swing.JButton createLoadFile;
	private javax.swing.JLabel createLoadFileLabel;
	private javax.swing.JScrollPane logPane;
	protected static javax.swing.JTextArea logText;
	private javax.swing.JLabel objectFile1Label;
	private javax.swing.JLabel objectFile2Label;
	private javax.swing.JLabel objectFile3Label;
	private javax.swing.JLabel outputLabel;
	private javax.swing.JButton quitButton;
	private javax.swing.JButton resetButton;
	private javax.swing.JButton saveLoadFile;
	private javax.swing.JLabel saveLoadFileLabel;
	private javax.swing.JButton selectObjectFile1;
	private javax.swing.JButton selectObjectFile2;
	private javax.swing.JButton selectObjectFile3;
	private javax.swing.JButton simulateButton;
	private javax.swing.JLabel simulateLabel;

	private javax.swing.JLabel titleLabel;
	private javax.swing.JSeparator topSeparator;

	/** Creates new form SP1GUI */
	public Main2() {
		initComponents();
		txtFilter = new FileNameExtensionFilter("Text File", "txt");
		objectFileText = "";
		this.objectFile1 = new File("");
		this.objectFile2 = new File("");
		this.objectFile3 = new File("");
		this.fcOpenOF1 = new JFileChooser();
		this.fcOpenOF2 = new JFileChooser();
		this.fcOpenOF3 = new JFileChooser();
		this.fcSave = new JFileChooser();
		this.getRootPane().setDefaultButton(this.selectObjectFile1);
		this.selectObjectFile1.requestFocusInWindow();
		this.logPane.setVisible(true);
	}

	/** This method is called from within the constructor to
	 * initialize the form.
	 * WARNING: Do NOT modify this code. The content of this method is
	 * always regenerated by the Form Editor.
	 */
	// <editor-fold defaultstate="collapsed" desc="Generated Code">
	private void initComponents() {

        titleLabel = new javax.swing.JLabel();
        resetButton = new javax.swing.JButton();
        quitButton = new javax.swing.JButton();
        topSeparator = new javax.swing.JSeparator();
        objectFile1Label = new javax.swing.JLabel();
        objectFile2Label = new javax.swing.JLabel();
        objectFile3Label = new javax.swing.JLabel();
        saveLoadFileLabel = new javax.swing.JLabel();
        createLoadFileLabel = new javax.swing.JLabel();
        simulateLabel = new javax.swing.JLabel();
        selectObjectFile1 = new javax.swing.JButton();
        selectObjectFile2 = new javax.swing.JButton();
        selectObjectFile3 = new javax.swing.JButton();
        saveLoadFile = new javax.swing.JButton();
        createLoadFile = new javax.swing.JButton();
        simulateButton = new javax.swing.JButton();
        bottomSeparator = new javax.swing.JSeparator();
        logPane = new javax.swing.JScrollPane();
        logText = new javax.swing.JTextArea();
        outputLabel = new javax.swing.JLabel();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setTitle("Assmble Your Code");
        setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR));
        setLocationByPlatform(true);
        setName("mainFrame"); // NOI18N

        titleLabel.setFont(new java.awt.Font("Tahoma", 1, 18));
        titleLabel.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        titleLabel.setText("CSE 560 - Group 01 - Linker/Loader & Simulator");
        titleLabel.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);

        resetButton.setText("Reset");
        resetButton.setToolTipText("Clicking this Button will Immediately Reset the Program");
        resetButton.setDefaultCapable(false);
        resetButton.setFocusPainted(false);
        resetButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                resetButtonActionPerformed(evt);
            }
        });

        quitButton.setText("Quit");
        quitButton.setToolTipText("Clicking this Button will Immediately Exit the Program");
        quitButton.setDefaultCapable(false);
        quitButton.setFocusPainted(false);
        quitButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                quitButtonActionPerformed(evt);
            }
        });

        objectFile1Label.setLabelFor(selectObjectFile1);
        objectFile1Label.setText("Select the First Object File.");

        objectFile2Label.setLabelFor(selectObjectFile2);
        objectFile2Label.setText("Select the Second Object File.");
        objectFile2Label.setEnabled(false);

        objectFile3Label.setLabelFor(selectObjectFile3);
        objectFile3Label.setText("Select the First Object File.");
        objectFile3Label.setEnabled(false);

        saveLoadFileLabel.setLabelFor(saveLoadFile);
        saveLoadFileLabel.setText("Select a location to save the load file.");
        saveLoadFileLabel.setEnabled(false);

        createLoadFileLabel.setLabelFor(createLoadFile);
        createLoadFileLabel.setText("Great! Click \"Create Load File\" to Create the Load File.");
        createLoadFileLabel.setEnabled(false);

        simulateLabel.setLabelFor(simulateButton);
        simulateLabel.setText("Click \"Simulate\" to Simulate the Load File.");
        simulateLabel.setEnabled(false);

        selectObjectFile1.setText("Select Object File 1...");
        selectObjectFile1.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                selectObjectFile1ActionPerformed(evt);
            }
        });

        selectObjectFile2.setText("Select Object File 2...");
        selectObjectFile2.setEnabled(false);
        selectObjectFile2.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                selectObjectFile2ActionPerformed(evt);
            }
        });

        selectObjectFile3.setText("Select Object File 3...");
        selectObjectFile3.setEnabled(false);
        selectObjectFile3.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                selectObjectFile3ActionPerformed(evt);
            }
        });

        saveLoadFile.setText("Save Load File...");
        saveLoadFile.setEnabled(false);
        saveLoadFile.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                saveLoadFileActionPerformed(evt);
            }
        });

        createLoadFile.setText("Create Load File");
        createLoadFile.setEnabled(false);
        createLoadFile.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                createLoadFileActionPerformed(evt);
            }
        });

        simulateButton.setText("Simulate");
        simulateButton.setEnabled(false);
        simulateButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                simulateButtonActionPerformed(evt);
            }
        });

        logPane.setVerticalScrollBarPolicy(javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
        logPane.setAutoscrolls(true);
        logPane.setMaximumSize(new java.awt.Dimension(32767, 100));

        logText.setColumns(20);
        logText.setEditable(false);
        logText.setLineWrap(true);
        logText.setRows(5);
        logText.setText("Output Log\n");
        logText.setToolTipText("This Text Box adds Output Messages when Assembling Code");
        logText.setWrapStyleWord(true);
        logText.setFocusable(true);
        logText.setMaximumSize(new java.awt.Dimension(2147483647, 100));
        logText.setRequestFocusEnabled(true);
        logText.setVerifyInputWhenFocusTarget(true);
        logPane.setViewportView(logText);

        outputLabel.setFont(new java.awt.Font("Tahoma", 1, 18));
        outputLabel.setHorizontalAlignment(javax.swing.SwingConstants.LEFT);
        outputLabel.setText("Output");
        outputLabel.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(titleLabel)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 405, Short.MAX_VALUE)
                .addComponent(resetButton, javax.swing.GroupLayout.PREFERRED_SIZE, 71, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(quitButton)
                .addContainerGap())
            .addComponent(bottomSeparator, javax.swing.GroupLayout.DEFAULT_SIZE, 984, Short.MAX_VALUE)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(outputLabel)
                .addContainerGap(911, Short.MAX_VALUE))
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(logPane, javax.swing.GroupLayout.DEFAULT_SIZE, 964, Short.MAX_VALUE)
                .addContainerGap())
            .addComponent(topSeparator, javax.swing.GroupLayout.DEFAULT_SIZE, 984, Short.MAX_VALUE)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                .addContainerGap(343, Short.MAX_VALUE)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
                    .addComponent(selectObjectFile1, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(selectObjectFile2, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(createLoadFile, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(saveLoadFile, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(selectObjectFile3, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(simulateButton, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                .addGap(18, 18, 18)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(createLoadFileLabel)
                    .addComponent(simulateLabel)
                    .addComponent(saveLoadFileLabel)
                    .addComponent(objectFile3Label)
                    .addComponent(objectFile2Label)
                    .addComponent(objectFile1Label))
                .addGap(225, 225, 225))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(titleLabel)
                    .addComponent(resetButton, javax.swing.GroupLayout.PREFERRED_SIZE, 25, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(quitButton, javax.swing.GroupLayout.PREFERRED_SIZE, 25, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(topSeparator, javax.swing.GroupLayout.PREFERRED_SIZE, 10, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(selectObjectFile1)
                    .addComponent(objectFile1Label))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(selectObjectFile2)
                    .addComponent(objectFile2Label))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(selectObjectFile3)
                    .addComponent(objectFile3Label))
                .addGap(18, 18, 18)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(saveLoadFile)
                    .addComponent(saveLoadFileLabel))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(createLoadFile)
                    .addComponent(createLoadFileLabel))
                .addGap(18, 18, 18)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(simulateButton)
                    .addComponent(simulateLabel))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(bottomSeparator, javax.swing.GroupLayout.PREFERRED_SIZE, 11, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(outputLabel)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(logPane, javax.swing.GroupLayout.DEFAULT_SIZE, 245, Short.MAX_VALUE)
                .addContainerGap())
        );

        pack();
    }// </editor-fold>

	private void quitButtonActionPerformed(java.awt.event.ActionEvent evt) {                                           
		System.exit(0);
	}                                          

	private void resetButtonActionPerformed(java.awt.event.ActionEvent evt) {                                            
		logText.setText(null);
		logText.append("Output Log\n");
		this.objectFileText = "";
		this.simulateLabel.setText("Click \"Simulate\" to Simulate the Load File.");
		this.createLoadFileLabel.setText("Great! Click \"Create Load File\" to Create the Load File.");
		this.selectObjectFile1.setEnabled(true);
		this.objectFile1Label.setEnabled(true);
		this.selectObjectFile2.setEnabled(true);
		this.objectFile2Label.setEnabled(true);
		this.selectObjectFile3.setEnabled(true);
		this.objectFile3Label.setEnabled(true);
		this.saveLoadFile.setEnabled(true);
		this.saveLoadFileLabel.setEnabled(true);

	}                                           

	private void selectObjectFile1ActionPerformed(java.awt.event.ActionEvent evt) {
		// TODO add your handling code here:
		fcOpenOF1.addChoosableFileFilter(this.txtFilter);
		if (this.fcOpenOF1.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) {
			this.objectFile1 = this.fcOpenOF1.getSelectedFile();
			this.objectFile1Label.setText(this.objectFile1.getAbsolutePath());
			this.selectObjectFile2.setEnabled(true);
			this.objectFile2Label.setEnabled(true);
			this.selectObjectFile3.setEnabled(true);
			this.objectFile3Label.setEnabled(true);
			this.saveLoadFile.setEnabled(true);
			this.saveLoadFileLabel.setEnabled(true);
			this.selectObjectFile2.requestFocusInWindow();
		}

	}

	private void selectObjectFile2ActionPerformed(java.awt.event.ActionEvent evt) {
		// TODO add your handling code here:
		fcOpenOF2.addChoosableFileFilter(this.txtFilter);
		if (this.fcOpenOF2.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) {
			this.objectFile2 = this.fcOpenOF2.getSelectedFile();
			this.objectFile2Label.setText(this.objectFile2.getAbsolutePath());
			this.selectObjectFile3.setEnabled(true);
			this.objectFile3Label.setEnabled(true);
			this.selectObjectFile3.requestFocusInWindow();
		}

	}

	private void selectObjectFile3ActionPerformed(java.awt.event.ActionEvent evt) {
		// TODO add your handling code here:
		fcOpenOF3.addChoosableFileFilter(this.txtFilter);
		if (this.fcOpenOF3.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) {
			this.objectFile3 = this.fcOpenOF3.getSelectedFile();
			this.objectFile3Label.setText(this.objectFile3.getAbsolutePath());
			this.saveLoadFile.setEnabled(true);
			this.saveLoadFileLabel.setEnabled(true);
			this.saveLoadFile.requestFocusInWindow();
		}
	}

	private void saveLoadFileActionPerformed(java.awt.event.ActionEvent evt) {
		// TODO add your handling code here:
		fcSave.addChoosableFileFilter(this.txtFilter);
		this.loadFile = new File("LoadFile.txt");
		fcSave.setSelectedFile(this.loadFile);
		if (fcSave.showSaveDialog(this) == JFileChooser.APPROVE_OPTION) {
			this.loadFile = this.fcSave.getSelectedFile();
			this.saveLoadFileLabel.setText(this.loadFile.getAbsolutePath());
			this.createLoadFile.setEnabled(true);
			this.createLoadFileLabel.setEnabled(true);
			this.createLoadFile.requestFocusInWindow();
		}
	}

	private void createLoadFileActionPerformed(java.awt.event.ActionEvent evt) {
		logText.setText(null);
		logText.append("LOAD FILE CREATION OUTPUT\n");
		compileObjectFiles();
		LoadMap.initialize();
		Loader.initialize();
		LoadFile.initilize();
		Linker.runLinker(objectFileText);
		
		String loadMapString = FileFormatter.formatLoadMap();
		Main2.appendDebugText(loadMapString);
		String loadFileString = FileFormatter.formatLoadFile();
		
		try {
			FileHandler.writeFile(loadFile, loadFileString);
		} catch (FileNotFoundException e) {
			Main2.appendDebugText("ERROR, file not found.\n" + e);
			e.printStackTrace();
		}
		
		this.simulateButton.setEnabled(true);
		this.simulateLabel.setEnabled(true);
		this.simulateButton.requestFocusInWindow();
		this.selectObjectFile1.setEnabled(false);
		this.objectFile1Label.setEnabled(false);
		this.selectObjectFile2.setEnabled(false);
		this.objectFile2Label.setEnabled(false);
		this.selectObjectFile3.setEnabled(false);
		this.objectFile3Label.setEnabled(false);
		this.saveLoadFile.setEnabled(false);
		this.saveLoadFileLabel.setEnabled(false);
		logText.append("\nLOAD FILE CREATED");
	}

	private void simulateButtonActionPerformed(java.awt.event.ActionEvent evt) {
		// TODO add your handling code here:
		logText.setText(null);
		logText.append("SIMULATION OUTPUT\n");
		Simulator.execute();
		logText.append("\nSIMULATION COMPLETE");
		this.simulateLabel.setText("\nSIMULATION COMPLETE");
	}

	public static void appendDebugText(String appendedText) {
		Main2.logText.append(appendedText + "\n");
	}

	private void compileObjectFiles() {
		StringBuilder obText = new StringBuilder();
		obText.append(FileHandler.readFile(objectFile1));
		if (objectFile2.exists()) {
			obText.append(FileHandler.readFile(objectFile2));
		}
		if (objectFile3.exists()) {
			obText.append(FileHandler.readFile(objectFile3));
		}
		objectFileText = obText.toString();
	}

	/**
	 * @param args the command line arguments
	 */
	public static void main(String args[]) {
		try {
			// Set System L&F
			UIManager.setLookAndFeel(
					UIManager.getSystemLookAndFeelClassName());
		}
		catch (UnsupportedLookAndFeelException e) {
			appendDebugText("Error: " + e);
			e.printStackTrace();
		}


		catch (ClassNotFoundException e) {
			Main2.appendDebugText("Error: " + e);
			e.printStackTrace();
		}		catch (InstantiationException e) {
			Main2.appendDebugText("Error: " + e);
			e.printStackTrace();
		}		catch (IllegalAccessException e) {
			Main2.appendDebugText("Error: " + e);
			e.printStackTrace();
		}

		java.awt.EventQueue.invokeLater(new Runnable() {

			@Override
			public void run() {
				new Main2().setVisible(true);
			}
		});
	}
}


